package com.snow.useviewdemo.gradien;

import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import androidx.appcompat.widget.AppCompatTextView;
import android.util.AttributeSet;

import com.snow.useviewdemo.R;

import gradient.mylibrary.Orientation;

/**
 * author : zyt
 * e-mail : 632105276@qq.com
 * date   : 2019/5/14
 * desc   :
 */
public class GradienTextView extends AppCompatTextView {
    private int mOriginalColor;
    private int mChangeColor;
    private Paint mOriginalPaint;
    private Paint mChangePaint;
    private Orientation orientation;
    private int baseLine;
    private float mCurrentProgress;

    public GradienTextView(Context context) {
        this(context, (AttributeSet)null);
    }

    public GradienTextView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public GradienTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.mOriginalColor = -16777216;
        this.mChangeColor = -65536;
        this.orientation = Orientation.LEFT_TO_RIGHT;
        TypedArray td = context.obtainStyledAttributes(attrs, R.styleable.GradienTextView);
        this.mOriginalColor = td.getColor(R.styleable.GradienTextView_original_color, this.mOriginalColor);
        this.mChangeColor = td.getColor(R.styleable.GradienTextView_change_color, this.mChangeColor);
        td.recycle();
        this.mOriginalPaint = this.getPaintByColor(this.mOriginalColor);
        this.mChangePaint = this.getPaintByColor(this.mChangeColor);
    }

    private Paint getPaintByColor(int color) {
        Paint paint = new Paint();
        paint.setColor(color);
        paint.setAntiAlias(true);
        paint.setDither(true);
        paint.setTextSize(this.getTextSize());
        return paint;
    }

    protected void onDraw(Canvas canvas) {
        float middle = this.mCurrentProgress * (float)this.getWidth();
        Paint.FontMetricsInt fontMetricsInt = this.mOriginalPaint.getFontMetricsInt();
        this.baseLine = (fontMetricsInt.bottom - fontMetricsInt.top) / 2 - fontMetricsInt.bottom + this.getHeight() / 2 + this.getPaddingTop() / 2 - this.getPaddingBottom() / 2;
        if (this.orientation == Orientation.LEFT_TO_RIGHT) {
            this.clipRect(canvas, 0.0F, middle, this.mChangePaint);
            this.clipRect(canvas, middle, (float)this.getWidth(), this.mOriginalPaint);
        } else if (this.orientation == Orientation.INNER_TO_OUTER) {
            this.clipRect(canvas, (float)this.getWidth() - middle, middle, this.mChangePaint);
            this.clipRect(canvas, middle, (float)this.getWidth() - middle, this.mOriginalPaint);
        } else if (this.orientation == Orientation.RIGHT_TO_LEFT) {
            this.clipRect(canvas, (float)this.getWidth() - middle, (float)this.getWidth(), this.mChangePaint);
            this.clipRect(canvas, 0.0F, (float)this.getWidth() - middle, this.mOriginalPaint);
        } else if (this.orientation == Orientation.RIGHT_TO_LEFT_FROM_NONE) {
            this.clipRect(canvas, (float)this.getWidth() - middle, (float)this.getWidth(), this.mChangePaint);
            this.clipRect(canvas, (float)this.getWidth(), (float)this.getWidth() - middle, this.mOriginalPaint);
        } else if (this.orientation == Orientation.LEFT_TO_RIGHT_FORME_NONE) {
            this.clipRect(canvas, 0.0F, middle, this.mChangePaint);
            this.clipRect(canvas, middle, 0.0F, this.mOriginalPaint);
        }

    }

    private void clipRect(Canvas canvas, float start, float region, Paint paint) {
        canvas.save();
        canvas.clipRect(start + (float)this.getPaddingLeft(), 0.0F, region, (float)this.getHeight());
        canvas.drawText(this.getText().toString(), (float)this.getPaddingLeft(), (float)this.baseLine, paint);
        canvas.restore();
    }

    public void setOrientation(Orientation orientation) {
        this.orientation = orientation;
    }

    public void setCurrentProgress(float currentProgress) {
        this.mCurrentProgress = currentProgress;
        this.invalidate();
    }

    public void start(final Orientation orientation, long duration) {
        ValueAnimator animator = ValueAnimator.ofFloat(new float[]{0.0F, 1.0F});
        animator.setDuration(duration);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            public void onAnimationUpdate(ValueAnimator animation) {
                float value = (Float)animation.getAnimatedValue();
                GradienTextView.this.setOrientation(orientation);
                GradienTextView.this.setCurrentProgress(value);
            }
        });
        animator.start();
    }
}
